package com.example.myapplication.utils

import android.content.Context
import android.util.Log
import com.bun.miitmdid.core.InfoCode
import com.bun.miitmdid.core.MdidSdkHelper
import com.bun.miitmdid.interfaces.IIdentifierListener
import com.bun.miitmdid.interfaces.IPermissionCallbackListener
import com.bun.miitmdid.interfaces.IdSupplier
import com.bun.miitmdid.pojo.IdSupplierImpl
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import kotlin.also

/**
 * Date: 16:27 2021/2/26 0026
 * Version: 1.0.3
 */
class DemoHelper // TODO （3）加固版本在调用前必须载入SDK安全库,因为加载有延迟，推荐在application中调用loadLibrary方法
// System.loadLibrary("msaoaidsec");
    (private val appIdsUpdater: AppIdsUpdater?, lib: String?) : IIdentifierListener {
    private var isCertInit = false
    var isSupported: Boolean = false
        private set
    var isLimited: Boolean = false
        private set
    var isSupportRequestOAIDPermission: Boolean = false
    var isSDKLogOn: Boolean = true // TODO （1）设置 是否开启sdk日志

    fun getDeviceIds(cxt: Context) {
        getDeviceIds(cxt, true, true, true)
    }

    /**
     * 获取OAID
     *
     * @param cxt
     */
    fun getDeviceIds(cxt: Context, isGetOAID: Boolean, isGetVAID: Boolean, isGetAAID: Boolean) {
        // TODO （4）初始化SDK证书
        startTimeMillis = System.nanoTime()


        if (!isCertInit) { // 证书只需初始化一次
            // 证书为PEM文件中的所有文本内容（包括首尾行、换行符）
            try {
                startTimeMillis = System.nanoTime()
                isCertInit = MdidSdkHelper.InitCert(cxt, loadPemFromAssetFile(cxt, ASSET_FILE_NAME_CERT))
            } catch (e: Error) {
                e.printStackTrace()
            }
            if (!isCertInit) {
                Log.w(TAG, "getDeviceIds: cert init failed")
            }
        }

        // （可选）设置InitSDK接口回调超时时间(仅适用于接口为异步)，默认值为5000ms.
        // 注：请在调用前设置一次后就不再更改，否则可能导致回调丢失、重复等问题
        try {
            MdidSdkHelper.setGlobalTimeout(5000)
        } catch (error: Error) {
            error.printStackTrace()
        }
        var code = 0
        // TODO （5）调用SDK获取ID
        try {
            // if x86 throws Error
            code = MdidSdkHelper.InitSdk(cxt, isSDKLogOn, isGetOAID, isGetVAID, isGetAAID, this)
        } catch (error: Error) {
            error.printStackTrace()
        } finally {
            val time: Long = endTimeMillis - startTimeMillis
            Log.d(TAG, "Time Consume:" + time)
        }

        // TODO （6）根据SDK返回的code进行不同处理
        val unsupportedIdSupplier = IdSupplierImpl()
        if (code == InfoCode.INIT_ERROR_CERT_ERROR) { // 证书未初始化或证书无效，SDK内部不会回调onSupport
            // APP自定义逻辑
            Log.w(TAG, "cert not init or check not pass")
            onSupport(unsupportedIdSupplier)
        } else if (code == InfoCode.INIT_ERROR_DEVICE_NOSUPPORT) { // 不支持的设备, SDK内部不会回调onSupport
            // APP自定义逻辑
            Log.w(TAG, "device not supported")
            onSupport(unsupportedIdSupplier)
        } else if (code == InfoCode.INIT_ERROR_LOAD_CONFIGFILE) { // 加载配置文件出错, SDK内部不会回调onSupport
            // APP自定义逻辑
            Log.w(TAG, "failed to load config file")
            onSupport(unsupportedIdSupplier)
        } else if (code == InfoCode.INIT_ERROR_MANUFACTURER_NOSUPPORT) { // 不支持的设备厂商, SDK内部不会回调onSupport
            // APP自定义逻辑
            Log.w(TAG, "manufacturer not supported")
            onSupport(unsupportedIdSupplier)
        } else if (code == InfoCode.INIT_ERROR_SDK_CALL_ERROR) { // sdk调用出错, SSDK内部不会回调onSupport
            // APP自定义逻辑
            Log.w(TAG, "sdk call error")
            onSupport(unsupportedIdSupplier)
        } else if (code == InfoCode.INIT_INFO_RESULT_DELAY) { // 获取接口是异步的，SDK内部会回调onSupport
            Log.i(TAG, "result delay (async)")
        } else if (code == InfoCode.INIT_INFO_RESULT_OK) { // 获取接口是同步的，SDK内部会回调onSupport
            Log.i(TAG, "result ok (sync)")
        } else {
            // sdk版本高于DemoHelper代码版本可能出现的情况，无法确定是否调用onSupport
            // 不影响成功的OAID获取
            Log.w(TAG, "getDeviceIds: unknown code: " + code)
        }
    }

    /**
     * APP自定义的getDeviceIds(Context cxt)的接口回调
     *
     * @param supplier
     */
    override fun onSupport(supplier: IdSupplier?) {
        if (supplier == null) {
            Log.w(TAG, "onSupport: supplier is null")
            return
        }
        if (appIdsUpdater == null) {
            Log.w(TAG, "onSupport: callbackListener is null")
            return
        }
        endTimeMillis = System.nanoTime()
        val isSupported: Boolean
        val isLimited: Boolean
        val oaid: String?
        val vaid: String?
        val aaid: String?
        // 获取Id信息
        // 注：IdSupplier中的内容为本次调用MdidSdkHelper.InitSdk()的结果，不会实时更新。
        // 如需更新，需调用MdidSdkHelper.InitSdk()
        isSupported = supplier.isSupported()
        isLimited = supplier.isLimited()
        oaid = supplier.getOAID()
        //vaid = supplier.getVAID()
        //aaid = supplier.getAAID()
        Log.d(TAG, "onSupport: oaid id: $oaid")
        this.setIsSupported(isSupported)
        this.setIsLimited(isLimited)
        this.isSupportRequestOAIDPermission = supplier.isSupportRequestOAIDPermission()
        appIdsUpdater.onIdsValid(oaid)
    }

    interface AppIdsUpdater {
        fun onIdsValid(ids: String?)
    }

    val timeConsume: Long
        get() =// 因为证书只初始化一次，所以这个只能获取一次
            endTimeMillis - startTimeMillis

    fun requestOAIDPermission(appContext: Context?, listener: IPermissionCallbackListener?) {
        MdidSdkHelper.requestOAIDPermission(appContext, listener)
    }

    fun setIsSupported(isSupported: Boolean): Boolean {
        return isSupported.also { this.isSupported = it }
    }

    fun setIsLimited(isLimited: Boolean): Boolean {
        return isLimited.also { this.isLimited = it }
    }

    companion object {
        var startTimeMillis: Long = 0
        var endTimeMillis: Long = 0
        const val TAG: String = "DemoHelper"
        const val ASSET_FILE_NAME_CERT: String = "com.mirrorbox.player.cert.pem"

        /**
         * 从asset文件读取证书内容
         *
         * @param context
         * @param assetFileName
         * @return 证书字符串
         */
        fun loadPemFromAssetFile(context: Context, assetFileName: String): String {
            try {
                val `is` = context.getAssets().open(assetFileName)
                val `in` = BufferedReader(InputStreamReader(`is`))
                val builder = StringBuilder()
                var line: String?
                while ((`in`.readLine().also { line = it }) != null) {
                    builder.append(line)
                    builder.append('\n')
                }
                return builder.toString()
            } catch (e: IOException) {
                Log.e(TAG, "loadPemFromAssetFile failed")
                return ""
            }
        }
    }
}
